[Agents for Amazon Bedrock] 簡素化された定義を試してみました
1 はじめに
CX事業本部製造ビジネステクノロジー部の平内(SIN)です。
Agents for Amazon Bedrockでアクションの定義を行う場合、次の2種類の方法があります。
- Set up an OpenAPI schema
- Set up function details
https://docs.aws.amazon.com/bedrock/latest/userguide/action-define.html
1.は、従来のOpenAPI標準のスキーマを準備する方法で、2.は、先月、新しく追加された簡素化された設定です。
Apr 23, 2024 - Amazon Bedrock のエージェントでエージェント作成が簡素化され、Return of Control 機能をリリース
今回は、最初にOpenAPIのスキーマを使用した従来の定義方法でエージェントを作成し、これを簡素化された定義に変更することで、その移行方法を確認してみました。
最初に、サンプルで作成したエージェントが動作している様子です。
このエージェントは、天気情報を取得して、服装をアドバイスするものです。 参照する地域が変わると、天気情報が変化するため、レコメンドも変化していることが分かると思います。
2 OpenAPIスキーマーによる設定
Action group typeでは、Define with API schemasを選択し、Action group schemaで、S3に配置されたOpenAPIスキーマーを指定しています。
Lambdaは、天気情報を取得するために使われています。
天気情報については、OpenWeatherMapから3時間毎の天気情報を取得し、9時間分を整形して配列で返しています。
[ {"日時": "2024-05-24 09:00:00+09:00", "天気": "厚い雲", "気温(℃)": 21.58, "気圧": 1007, ・・・・}, {"日時": "2024-05-24 12:00:00+09:00", "天気": "晴れ", "気温(℃)": 27.18, "気圧": 1007, ・・・}, {"日時": "2024-05-24 15:00:00+09:00", "天気": "雨", "気温(℃)": 25.71, "気圧": 1006, "湿度": 33・・・} ]
なお、都市については環境変数で指定されており、使用場所に応じて変化させる想定です。
Lambda
import datetime import json import os import requests import pytz def create_forecast_item(item): date_str = str( datetime.datetime.fromtimestamp(item["dt"], pytz.timezone("Asia/Tokyo")) ) # 日時 weather = item["weather"][0]["description"] # 天気 feels_like = item["main"]["feels_like"] # 体感温度 pressure = item["main"]["pressure"] # 気圧 humidity = item["main"]["humidity"] # 湿度 wind = item["wind"]["speed"] # 風速 clouds = item["clouds"]["all"] # 曇り率(%) rainfall = item.get("rain", {}).get("3h", 0) # 雨量(mm) return { "日時": date_str, "天気": weather, "気温(℃)": feels_like, "気圧": pressure, "湿度": humidity, "風速": wind, "曇り率(%)": clouds, "雨量(mm)": rainfall, } def get_weather_forecast(city, api_key): url = "http://api.openweathermap.org/data/2.5/forecast?q={}&appid={}&lang=ja&units=metric".format( city, api_key ) forecast_data = requests.get(url).json() if "list" in forecast_data: list = forecast_data["list"] return [create_forecast_item(item) for i, item in enumerate(list) if i < 3] return [] def lambda_handler(event, context): city = os.getenv("CITY") api_key = os.getenv("API_KEY") forecast = get_weather_forecast(city, api_key) response = { "actionGroup": event["actionGroup"], "apiPath": event["apiPath"], "httpMethod": event["httpMethod"], "httpStatusCode": 200, "responseBody": { "application/json": { "body": json.dumps({"forecast": forecast}, ensure_ascii=False) } }, } api_response = {"messageVersion": "1.0", "response": response} return api_response
OpenAPIのスキーマは、以下のとおりです。
openapi.yaml
openapi: 3.0.0 info: title: 天気取得API version: 1.0.0 description: 3時間毎の天気情報を取得するAPI paths: /get_weather: post: summary: 3時間毎の天気情報を取得するAPI description: 3時間毎の天気情報が配列で返されます operationId: get_weather requestBody: required: true content: application/json: schema: type: object responses: "200": description: articless response content: application/json: schema: type: object properties: article: type: string description: 天気情報の配列
エージェント向けの指示
あなたは、外出の服装を、{天気}に合わせてアドバイスするファッションのプロです。 {天気}は{天気取得API}から取得できます。 ファッション・服装に関する事項は、エージェント自身で考えてください アドバイスには、女性向けに具体的な服装を教えて下さい アドバイスには、天気の情報や、注意事項を含めてください アドバイスには、ちょっとした励ましの言葉を追加してください ### 会話の例 ユーザー:何を着て行けばいいでしょう? エージェント:日中は穏やかですが、朝夕、気温が下がるので、少し上から羽織るものも用意したほうが良いでしょう。良い日になりますように! ユーザー:今日、着ていく服のアドバイスを下さい エージェント:今日は一日雨の予報です。小雨なので濡れる心配は少ないですが、長靴やレインコートを持っていくことをおすすめします。気温は朝が13度くらいで、日中は12度くらいに下がる見込みです。湿度も高いので、少し厚手の上着を羽織ることをおすすめします。楽しんで来てください! ユーザー:どんな服装で出かければいいでしょう? エージェント:朝は晴れですが、気温が低めですので、長袖の上着を羽織ることをおすすめします。 日中は高温多湿なので、半袖で過ごしやすいでしょう。日傘があると良いでしょう。 雨も少し降る可能性があるので、折り畳み傘を持参することをおすすめします。 楽しい1日になりますように!
3 簡素化された設定
続いて、簡素化された設定に変更してみます。
Action group typeでは、Define with function detailsの選択となり、Action group functionで、Lambdaの機能の説明や、パラメータ設定を行っています。(※今回は、Lambdaのパラメータは使用されていません)
実は、設定だけを変更してエージェントを使用すると、下記のようにLambdaの呼び出しが失敗します。
この原因は、簡素化された設定を使用する場合、Lmabdaのリクエスト及び、レスポンスの形式が変わるためです。
Lambdaのレスポンスを下記のように変更することで、エラー無く利用できるようになります。
def lambda_handler(event, context): city = os.getenv("CITY") api_key = os.getenv("API_KEY") forecast = get_weather_forecast(city, api_key) # 簡素化された設定の場合 response = { "actionGroup": event["actionGroup"], "function": event["function"], "functionResponse": { "responseBody": { "TEXT": {"body": json.dumps({"forecast": forecast}, ensure_ascii=False)} } }, } # OpenAPI Schemaの場合 # response = { # "actionGroup": event["actionGroup"], # "apiPath": event["apiPath"], # "httpMethod": event["httpMethod"], # "httpStatusCode": 200, # "responseBody": { # "application/json": { # "body": json.dumps({"forecast": forecast}, ensure_ascii=False) # } # }, # } api_response = {"messageVersion": "1.0", "response": response} return api_response
今回は、Lambdaへのパラメータを使用していないので、上記の修正(レスポンス)だけで作業は完了でしたが、パラメータを使用している場合は、そこの修正も必要になります。
それぞれのパラメータ及び、レスポンスの形式については、下記にドキュメントがあります。
Configure Lambda functions to send information an Amazon Bedrock agent elicits from the user to fulfill an action groups in Amazon Bedrock
4 最後に
今回は、エージェントのアクション定義で「簡素化されたもの」を試してみました。 OpenAPIスキーマを準備するより、圧倒的に手軽だし、すべてがコンソール上で定義できるので、手返しも良くなって全然いい感じでした。
Set up function details 一択でいいのでは・・・って思ってしまってます。
5 参考にさせて頂いたリンク
Create an action group for an Amazon Bedrock agent
PDF
【WebAPI】OpenWeatherMapで3時間ごとの天気を取りたい【json】